package com.wlz.aop.earlyAop;

import com.wlz.aop.Calculate;
import com.wlz.aop.MyCalculate;
import org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor;
import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
import org.springframework.context.annotation.Bean;

/**
 *
 * * Spring常见代理创建方式
 *      * FactoryBean方式，创建单个动态代理： ProxyFactoryBean  1.指定续增强的接口:proxyInterfaces  2.指定需增强的实现类target   3.指定Advice、Advisor、Interceptor都行
 *      * autoProxy方式：批量根据advisor自动创建
 *      * BeanPostProcessor手动指定Advice方式  BeanNameAutoProxyCreator  1.指定Advice  2.可以使用正则来匹配 bean 的名字
 *      * BeanPostProcessor自动扫描Advisor方式  DefaultAdvisorAutoProxyCreator  (不支持注解)、
 *      *         AnnotationAwareAspectJAutoProxyCreator（注解）、
 *      *         AspectJAwareAdvisorAutoProxyCreator（XML）
 *
 * @author wlz
 * @date 2022-05-28  3:43 下午
 */
public class EarlyAopConfig {

	/**
	 *  被代理的对象
	 * @return
	 */
	@Bean
	public Calculate myCalculate() {
		return new MyCalculate();
	}

	/**
	 *  Advice 方式
	 * @return
	 */
	@Bean
	public MyLogAdvice myLogAdvice() {
		return new MyLogAdvice();
	}

	/**
	 *  Interceptor 方式，类似环绕通知
	 * @return
	 */
	@Bean
	public MyLogInterceptor myLogInterceptor() {
		return new MyLogInterceptor();
	}


	/******************************  test4()  **************************/

	/**
	 *  BeanPostProcessor 自动扫描Advisor 方式 DefaultBeanFactoryPointcutAdvisor
	 * @return
	 */
	@Bean
	public DefaultBeanFactoryPointcutAdvisor autoProxyCreator() {
		return new DefaultBeanFactoryPointcutAdvisor();
	}

	/**
	 *  定 配置代理  按正则 匹配类
	 * @return
	 */
	@Bean
	public RegexpMethodPointcutAdvisor myLogAspectInterceptor() {
		RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor();
		advisor.setAdvice(myLogInterceptor());
		advisor.setPattern("com.wlz.aop.MyCalculate.*");
		return advisor;

	}

	/******************************  test3()  **************************/


	/**
	 *  自定 配置代理 BeanNameAutoProxyCreator
	 * @return
	 */
//	@Bean
//	public BeanNameAutoProxyCreator autoProxyCreator() {
//		BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
//		// 设置要创建代理的那些bean 的名字
//		beanNameAutoProxyCreator.setBeanNames("my*");
//		// 设置拦截链的名字（有先后顺序）粒度到类
////		beanNameAutoProxyCreator.setInterceptorNames("myLogInterceptor","myLogAdvice");
//		// 粒度到方法
//		beanNameAutoProxyCreator.setInterceptorNames("myLogAspectAdvisor");
//		return beanNameAutoProxyCreator;
//	}

	/******************************  test2()  **************************/


	/**
	 *  控制粒度到方法
	 */
//	@Bean
//	public NameMatchMethodPointcutAdvisor myLogAspectAdvisor() {
//		NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor();
//		advisor.setAdvice(myLogAdvice());
////		advisor.setAdvice(myLogInterceptor()); // 如果再setAdvice 会覆盖
//		advisor.setMappedNames("div");
//		return advisor;
//	}

	/**
	 *  控制粒度到方法
	 * @return
	 */
//	@Bean
//	public ProxyFactoryBean calculateProxy() {
//		ProxyFactoryBean userService = new ProxyFactoryBean();
//		userService.setInterceptorNames("myLogAspectAdvisor");
//		userService.setTarget(myCalculate());
//		return userService;
//	}


	/******************************  test()  **************************/

	/**
	 * FactoryBean方式单个： ProxyFactoryBean
	 *
	 * 此中方法有个致命的问题，如果我们只能指定单一的Bean的AOP，
	 * 如果多个Bean需要创建多个ProxyFactoryBean 。
	 * 而且，我们看到，我们的拦截器的粒度只控制到了类级别，类中所有的方法都进行了拦截。
	 * 接下来，我们看看怎么样只拦截特定的方法。
	 * @return
	 */
//	@Bean
//	public ProxyFactoryBean calculateProxy() {
//		ProxyFactoryBean userService = new ProxyFactoryBean();
//		userService.setInterceptorNames("myLogAdvice", "myLogInterceptor");
//		userService.setTarget(myCalculate());
//		return userService;
//	}

}
